#include "Metgine/Core/Renderer.hpp"
#include "Metgine/Core/Camera.hpp"
#include "Metgine/Core/Log.hpp"
#include "Metgine/Core/ResourceManager.hpp"

namespace Metgine
{

namespace Core
{

Renderer::Renderer() :
    m_camera(NULL),
    m_defaultFont(NULL)
{
}

Renderer::~Renderer()
{
    Log::Get()->Write(LogType::Message, "Shutdown");
}


void Renderer::Initialize(int width, int height, int colorDepth, const char* title, bool fullscreen)
{
    m_resolution.x = width;
    m_resolution.y = height;

    m_fullscreen = fullscreen;

    m_windowTitle = title;

    UpdateWindow();
}

void Renderer::UpdateWindow()
{

    m_window.Close();

    unsigned long style = sf::Style::Close;

    if (m_fullscreen)
        style |= sf::Style::Fullscreen;

    m_window.Create(sf::VideoMode(m_resolution.x, m_resolution.y, 32), m_windowTitle, style);
    m_window.UseVerticalSync(true);
    m_window.SetFramerateLimit(60);
    m_window.EnableKeyRepeat(true);
}

void Renderer::DoEvents()
{
    sf::Event e;
    while(m_window.GetEvent(e))
    {
        if (e.Type == sf::Event::Closed)
            m_window.Close();
    }
}

void Renderer::Clear(sf::Color clearColor)
{
    if (m_camera)
        m_window.SetView(m_camera->GetView());
    m_window.Clear(clearColor);
}

void Renderer::Present()
{
    if (m_camera)
        m_window.SetView(m_window.GetDefaultView());

    m_window.Display();
}

void Renderer::Render(const Graphics::Renderable& renderable)
{
    m_window.Draw(renderable.GetData());
}


void Renderer::SetDefaultFont(FontResource* font)
{
    if (font != NULL)
        m_defaultFont = font;
}

void Renderer::RenderText(float x, float y, FontResource* fontResource, const std::string& text, float size, const sf::Color& color, unsigned int flags)
{

    FontResource* font = NULL;

    if (fontResource == NULL)
    {

        if (m_defaultFont != NULL)
            font = m_defaultFont;

    }
    else
        font = fontResource;

    if (!font)
    {
        Log::Get()->Write(LogType::Error, "NO DEFAULT FONT ERROR ERROR!!!");
        return;
    }

    sf::String outString(text, font->GetFont(), size);

    if (flags & FontFlag::Centered)
    {
        sf::FloatRect bounds = outString.GetRect();
        outString.SetPosition(x - bounds.GetWidth() / 2, y - bounds.GetHeight() / 2);
    }
    else
        outString.SetPosition(x, y);

    outString.SetColor(color);

    unsigned long style = 0;

    if (flags & FontFlag::Bold)
        style |= sf::String::Bold;

    outString.SetStyle(style);

    m_window.Draw(outString);

}

BoundingBoxf Renderer::MeasureText(const std::string& text, FontResource* fontResource, float size)
{

    FontResource* font = NULL;

    if (fontResource == NULL)
    {

        if (m_defaultFont != NULL)
            font = m_defaultFont;

    }
    else
        font = fontResource;

    sf::String outString(text, font->GetFont(), size);
    sf::FloatRect bounds = outString.GetRect();

    Vector2f extents = Vector2f(bounds.GetWidth() * 0.5f, bounds.GetHeight() * 0.5f);
    return BoundingBoxf(Vector2f(bounds.Left + extents.x, bounds.Top + extents.y), extents);

}

void Renderer::RenderTextShadowed(float x, float y, FontResource* fontResource, const std::string& text, const float spacing, float size, const sf::Color& color, const sf::Color& shadow, unsigned int flags)
{
    RenderText(x + spacing, y + spacing, fontResource, text, size, shadow, flags);
    RenderText(x, y, fontResource, text, size, color, flags);

}

sf::RenderWindow& Renderer::GetWindow()
{
    return m_window;
}

void Renderer::SetIcon(sf::Image& image)
{
    m_window.SetIcon(image.GetWidth(), image.GetHeight(), image.GetPixelsPtr());
}

void Renderer::SetCamera(Camera* camera)
{
    if (!camera)
        m_camera = camera;
}

void Renderer::SetFullscreen(bool state)
{
    m_fullscreen = state;
    UpdateWindow();
}

bool Renderer::IsFullscreen()
{
    return m_fullscreen;
}

void Renderer::SetTitle(const std::string& title)
{
    m_windowTitle = title;
    UpdateWindow();
}

int Renderer::GetWidth() const
{
    return m_window.GetWidth();
}

int Renderer::GetHeight() const
{
    return m_window.GetHeight();
}

}; // Graphics

}; // Metgine
